package com.buka.recipe.security;

import com.buka.recipe.security.filter.JsonAuthenticationProcessingFilter;
import com.buka.recipe.security.filter.WechatAuthenticationFilter;
import com.buka.recipe.security.handler.JsonAuthenticationFailureHandler;
import com.buka.recipe.security.handler.JsonAuthenticationSuccessHandler;
import com.buka.recipe.security.provider.WechatAuthenticationProvider;
import com.buka.recipe.system.service.UserService;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.SecurityConfigurer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.DefaultSecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
import org.springframework.stereotype.Component;

/**
 * @author halo
 */
@Log4j2
@Component
public class JsonAuthenticationSecurityConfig implements SecurityConfigurer<DefaultSecurityFilterChain, HttpSecurity> {

    private final UserService userService;
    private final JsonAuthenticationSuccessHandler jsonAuthenticationSuccessHandler;
    private final JsonAuthenticationFailureHandler jsonAuthenticationFailureHandler;

    @Autowired
    public JsonAuthenticationSecurityConfig(UserService userService, JsonAuthenticationSuccessHandler jsonAuthenticationSuccessHandler,
                                            JsonAuthenticationFailureHandler jsonAuthenticationFailureHandler) {
        this.userService = userService;
        this.jsonAuthenticationSuccessHandler = jsonAuthenticationSuccessHandler;
        this.jsonAuthenticationFailureHandler = jsonAuthenticationFailureHandler;
    }

    @Override
    public void init(HttpSecurity builder) {

    }

    @Override
    public void configure(HttpSecurity http) {
        DaoAuthenticationProvider userDaoAuthenticationProvider = new DaoAuthenticationProvider();
        userDaoAuthenticationProvider.setUserDetailsService(userService);
        userDaoAuthenticationProvider.setPasswordEncoder(new BCryptPasswordEncoder());

        WechatAuthenticationProvider wechatAuthenticationProvider = new WechatAuthenticationProvider(userService);
        WechatAuthenticationFilter wechatAuthenticationFilter = new WechatAuthenticationFilter();
        wechatAuthenticationFilter.setAuthenticationManager(http.getSharedObject(AuthenticationManager.class));

        JsonAuthenticationProcessingFilter filter = new JsonAuthenticationProcessingFilter();

        filter.setAuthenticationManager(http.getSharedObject(AuthenticationManager.class));

        SessionAuthenticationStrategy sessionAuthenticationStrategy = http.getSharedObject(SessionAuthenticationStrategy.class);
        if (sessionAuthenticationStrategy != null) {
            filter.setSessionAuthenticationStrategy(sessionAuthenticationStrategy);
            wechatAuthenticationFilter.setSessionAuthenticationStrategy(sessionAuthenticationStrategy);
        }

        // 配置SessionRepository，不然一直提示未登录
        filter.setSecurityContextRepository(new HttpSessionSecurityContextRepository());
        wechatAuthenticationFilter.setSecurityContextRepository(new HttpSessionSecurityContextRepository());

        // 登录成功处理器
        filter.setAuthenticationSuccessHandler(jsonAuthenticationSuccessHandler);
        wechatAuthenticationFilter.setAuthenticationSuccessHandler(jsonAuthenticationSuccessHandler);
        // 登录失败处理器
        filter.setAuthenticationFailureHandler(jsonAuthenticationFailureHandler);
        wechatAuthenticationFilter.setAuthenticationFailureHandler(jsonAuthenticationFailureHandler);

        http.authenticationProvider(userDaoAuthenticationProvider)
                .addFilterAfter(filter, UsernamePasswordAuthenticationFilter.class);
        http.authenticationProvider(wechatAuthenticationProvider)
                .addFilterAfter(wechatAuthenticationFilter, JsonAuthenticationProcessingFilter.class);

    }
}
